#include "ustc_comdef.h"
#include "ustc_hif.h"
#include "ustc_api.h"

extern SD_PARA_T *gp_para_sd;

extern USTC_U32 sd_fifo_test(void);
#if (S3C44B0_TEST_PLATFORM==0)
USTC_U32 *buf_read=(USTC_U32*)0x01000000;
USTC_U32 *buf_write=(USTC_U32*)0x01004000;
#else
USTC_U32 *buf_read=(USTC_U32*)0x0C010000;
USTC_U32 *buf_write=(USTC_U32*)0x0C014000;
#endif

USTC_U32 dat_err_cnt[8];
USTC_U32 cmd_err_cnt[8];

#ifndef _TEST_PATTERN_
extern SD_PARA_T para_sd;
int test_sd()
#else
SD_PARA_T para_sd;
int c_main()
#endif
{
	USTC_U32 ret=0;
	USTC_U32 lba=0;
	USTC_U32 loop=0;
	USTC_U32 i;
	
	gp_para_sd=&para_sd;

	gp_para_sd->sd_cmd_timeout=0x100000;
	gp_para_sd->sd_timeout=0x100000;
	gp_para_sd->sd_line_mode = 1;
	gp_para_sd->sd_clk_phase_cfg=1;
	
#if (S3C44B0_TEST_PLATFORM==0)
	gp_para_sd->ustc_sdc_init_delay1=0x1000;
	gp_para_sd->ustc_sdc_init_delay2=0x1000;
#else
	gp_para_sd->ustc_sdc_init_delay1=0x4000;
	gp_para_sd->ustc_sdc_init_delay2=0x4000;
#endif
	gp_para_sd->sd_index = 0;
	gp_para_sd->sd_clk_div = 0x300;

	outph(HIF_TP_RW_CMD,0);

	ustc_outh(HIF_PLL_CFG, 0x2F0C);

	ustc_delay(1000000);
	
	ustc_outh(HIF_SYS_CLK_EN, HIF_CLK_EN_SD|HIF_CLK_EN_SD_RAM);

	
//	ustc_outh(HIF_REG_DATA, 0x1234);
//	ret=ustc_inh(HIF_REG_DATA);

//	USTC_IO_OUTW(HW_SD_TIMEOUT, 0x12345678);
//	ret=USTC_IO_INW(HW_SD_TIMEOUT);
	ret=sd_fifo_test();
	
//	ustc_outh(HIF_SYS_SW_RST, HIF_RST_USB|HIF_RST_SD_REG);
//	ustc_outh(HIF_SYS_SW_RST, 0);

	do {
		ustc_outh(HIF_SYS_SW_RST, HIF_RST_SD_REG|HIF_RST_SD);
		ustc_outh(HIF_SYS_SW_RST, 0);
		ustc_sdc_init(gp_para_sd);
	}while (gp_para_sd->sd_block_number==0);

	for (i=0; i<8; i++)
	{
		dat_err_cnt[i]=0;
		cmd_err_cnt[i]=0;
	}
	
	for (i=0; i<128; i++)
		buf_write[i]=(i<<24)|(i<<16)|(i<<8)|i;

	lba=0;

//	ustc_outh(HIF_SYS_SW_RST, HIF_RST_USB);
//	ustc_outh(HIF_SYS_SW_RST, 0);
	
//	while (lba<gp_para_sd->sd_block_number-32 && err_count<4096)
	do {
		while (lba<0x800)
		{
			ret=ustc_sdc_write(buf_write, lba, 1);
			ret|=ustc_sdc_read(buf_read, lba, 1);

			for (i=0; i<128; i++)
				if (buf_read[i]!=buf_write[i])
				{
					dat_err_cnt[(gp_para_sd->sd_clk_div>>8)-1]++;
					break;
				}

			lba++;
		}

		if (ret)
			cmd_err_cnt[(gp_para_sd->sd_clk_div>>8)-1]++;

		gp_para_sd->sd_clk_div += 0x100;

		if (gp_para_sd->sd_clk_div > 0x700)
		{
			gp_para_sd->sd_clk_div = 0x100;
		}
		
		lba=0;
	}while(++loop<8);
	
	return ret;
}

#if 1
#define HW_SD_FIFO_POINT 0x105C
USTC_U32 sd_fifo_test()
{
	USTC_U32 i;
	USTC_U32 data[129];
	USTC_U32 data_in=0xffffffff;
	USTC_U32 *pdata=&i;
	USTC_U32 err_cnt=0;

	for (i=0; i<512; i+=4)
	{
		data_in=USTC_IO_INW(HW_SD_FIFO_POINT);
		USTC_IO_OUTW(0x1080, (*pdata<<24)|(*pdata<<12)|*pdata);
	}
	data_in=USTC_IO_INW(HW_SD_FIFO_POINT);
	for (i=0; i<512; i+=4)
	{
		data_in=USTC_IO_INW(HW_SD_FIFO_POINT);
		data[i/4]=USTC_IO_INW(0x1080);
		if (data[i/4]!=((data[i/4]<<24)|(data[i/4]<<12)|data[i/4]))
			err_cnt++;
	}
	data_in=USTC_IO_INW(HW_SD_FIFO_POINT);

	return err_cnt;
}
#endif

